package com.kecheng.servermonitor.controller;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.kecheng.servermonitor.entity.DiskUsage;
import com.kecheng.servermonitor.entity.ServiceStatus;
import com.kecheng.servermonitor.entity.StatusReportRequest;
import lombok.Getter;
import org.springframework.web.bind.annotation.*;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api")
public class DeviceStatusController {


    // 缓存 clientId -> DeviceStatus
    private final Cache<String, DeviceStatus> statusCache = Caffeine.newBuilder()
            .expireAfterWrite(1, TimeUnit.MINUTES)
            .maximumSize(10_000)
            .build();

    /**
     * 前端上报状态，同时返回所有客户端状态
     */
    @PostMapping("/report-status-front")
    public List<DeviceStatus> reportStatus(
            @RequestBody StatusReportRequest statusReportRequest,
            @RequestHeader("email") String email,
            @RequestHeader("client-id") String rawClientId) {

        //解码
        final String clientId = safeDecode(rawClientId);

        //判定服务是否异常
        boolean hasAbnormalService = statusReportRequest.getServiceStatuses()
                .stream()
                .anyMatch(s -> !Boolean.TRUE.equals(s.isHealthy()));

        //组装 DeviceStatus 对象
        DeviceStatus deviceStatus = new DeviceStatus(
                clientId,
                statusReportRequest.getCpuUsage(),
                statusReportRequest.getMemoryUsage(),
                statusReportRequest.getDiskUsage(),
                statusReportRequest.getServiceStatuses(),
                hasAbnormalService
        );

        //更新缓存
        statusCache.put(clientId, deviceStatus);
        System.out.println("更新状态: " + deviceStatus);
        return new ArrayList<>(statusCache.asMap().values());
    }

    /**
     * 解码 client-id 的小工具方法
     */
    private String safeDecode(String value) {
        try {
            return URLDecoder.decode(value, StandardCharsets.UTF_8.name());
        } catch (Exception e) {
            System.out.println("client-id 解码失败，原始值: " + value);
            return value;
        }
    }


    /**
     * 前端调用接口，获取所有客户端最新状态
     */
    @GetMapping("/get-status-list")
    public List<ClientStatusDTO> getStatusList() {
        return statusCache.asMap().values().stream()
                .map(DeviceStatus::toClientStatusDTO)
                .collect(Collectors.toList());
    }

    // --- 辅助类 ---
    @Getter
    public static class DeviceStatus {
        private final String clientId;
        private final Double cpuUsage;
        private final int memoryUsage;
        private final List<DiskUsage> disks;
        private final List<ServiceStatus> services;
        private final boolean hasAbnormalService;

        public DeviceStatus(String clientId, Double cpuUsage, int memoryUsage,
                            List<DiskUsage> disks, List<ServiceStatus> services,
                            boolean hasAbnormalService) {
            this.clientId = clientId;
            this.cpuUsage = cpuUsage;
            this.memoryUsage = memoryUsage;
            this.disks = disks;
            this.services = services;
            this.hasAbnormalService = hasAbnormalService;
        }


        // 转 DTO 给前端使用
        public ClientStatusDTO toClientStatusDTO() {
            return new ClientStatusDTO(clientId, cpuUsage, memoryUsage, disks, services, hasAbnormalService);
        }

        @Override
        public String toString() {
            return "DeviceStatus{" +
                    "clientId='" + clientId + '\'' +
                    ", cpuUsage=" + cpuUsage +
                    ", memoryUsage=" + memoryUsage +
                    ", disks=" + disks +
                    ", services=" + services +
                    ", hasAbnormalService=" + hasAbnormalService +
                    '}';
        }
    }



    /**
     * DTO 给前端调用
     */
    @Getter
    public static class ClientStatusDTO {
        private final String clientId;
        private final Double cpuUsage;
        private final int memoryUsage;
        private final List<DiskUsage> disks;
        private final List<ServiceStatus> services;
        private final boolean hasAbnormalService;

        public ClientStatusDTO(String clientId, Double cpuUsage, int memoryUsage,
                               List<DiskUsage> disks, List<ServiceStatus> services,
                               boolean hasAbnormalService) {
            this.clientId = clientId;
            this.cpuUsage = cpuUsage;
            this.memoryUsage = memoryUsage;
            this.disks = disks;
            this.services = services;
            this.hasAbnormalService = hasAbnormalService;
        }

    }
}
